home *** CD-ROM | disk | FTP | other *** search
- //: C20:BankTeller.cpp
- // From Thinking in C++, 2nd Edition
- // Available at http://www.BruceEckel.com
- // (c) Bruce Eckel 1999
- // Copyright notice in Copyright.txt
- // Using a queue and simulated multithreading
- // To model a bank teller system
- #include <iostream>
- #include <queue>
- #include <list>
- #include <cstdlib>
- #include <ctime>
- using namespace std;
-
- class Customer {
- int serviceTime;
- public:
- Customer() : serviceTime(0) {}
- Customer(int tm) : serviceTime(tm) {}
- int getTime() { return serviceTime; }
- void setTime(int newtime) {
- serviceTime = newtime;
- }
- friend ostream&
- operator<<(ostream& os, const Customer& c) {
- return os << '[' << c.serviceTime << ']';
- }
- };
-
- class Teller {
- queue<Customer>& customers;
- Customer current;
- static const int slice = 5;
- int ttime; // Time left in slice
- bool busy; // Is teller serving a customer?
- public:
- Teller(queue<Customer>& cq)
- : customers(cq), ttime(0), busy(false) {}
- Teller& operator=(const Teller& rv) {
- customers = rv.customers;
- current = rv.current;
- ttime = rv.ttime;
- busy = rv.busy;
- return *this;
- }
- bool isBusy() { return busy; }
- void run(bool recursion = false) {
- if(!recursion)
- ttime = slice;
- int servtime = current.getTime();
- if(servtime > ttime) {
- servtime -= ttime;
- current.setTime(servtime);
- busy = true; // Still working on current
- return;
- }
- if(servtime < ttime) {
- ttime -= servtime;
- if(!customers.empty()) {
- current = customers.front();
- customers.pop(); // Remove it
- busy = true;
- run(true); // Recurse
- }
- return;
- }
- if(servtime == ttime) {
- // Done with current, set to empty:
- current = Customer(0);
- busy = false;
- return; // No more time in this slice
- }
- }
- };
-
- // Inherit to access protected implementation:
- class CustomerQ : public queue<Customer> {
- public:
- friend ostream&
- operator<<(ostream& os, const CustomerQ& cd) {
- copy(cd.c.begin(), cd.c.end(),
- ostream_iterator<Customer>(os, ""));
- return os;
- }
- };
-
- int main() {
- CustomerQ customers;
- list<Teller> tellers;
- typedef list<Teller>::iterator TellIt;
- tellers.push_back(Teller(customers));
- srand(time(0)); // Seed random number generator
- while(true) {
- // Add a random number of customers to the
- // queue, with random service times:
- for(int i = 0; i < rand() % 5; i++)
- customers.push(Customer(rand() % 15 + 1));
- cout << '{' << tellers.size() << '}'
- << customers << endl;
- // Have the tellers service the queue:
- for(TellIt i = tellers.begin();
- i != tellers.end(); i++)
- (*i).run();
- cout << '{' << tellers.size() << '}'
- << customers << endl;
- // If line is too long, add another teller:
- if(customers.size() / tellers.size() > 2)
- tellers.push_back(Teller(customers));
- // If line is short enough, remove a teller:
- if(tellers.size() > 1 &&
- customers.size() / tellers.size() < 2)
- for(TellIt i = tellers.begin();
- i != tellers.end(); i++)
- if(!(*i).isBusy()) {
- tellers.erase(i);
- break; // Out of for loop
- }
- }
- } ///:~
-